import type {MenuDataItem, Settings as LayoutSettings} from '@ant-design/pro-components';
import type {RunTimeLayoutConfig} from '@umijs/max';
import {history} from '@umijs/max';
import defaultSettings from '../config/defaultSettings';
import {
  currentUser as queryCurrentUser,
  currentUserMenus as queryCurrentUserMenus
} from './services/ant-design-pro/api';
import React from 'react';
import {AvatarDropdown, AvatarName} from './components/RightContent/AvatarDropdown';
import {message} from 'antd';
import Cookie from "js-cookie";
import {DashboardOutlined, MinusCircleOutlined, PlusCircleOutlined, SettingOutlined} from "@ant-design/icons";
const loginPath = '/login';
const mobileLoginPath = '/m/login';

// 检测请求连接是否免登录
function NoNeedLoginPath(path: string) {
  const noNeedToLoginPath = [
    'm/login',
    'login',
    'autoLogin',
    'firstLogin'
  ]
  // eslint-disable-next-line array-callback-return
  noNeedToLoginPath.map((item: string)=>{
    if (path.indexOf(item) !== -1){

      // 请求链路包含无需登录即可访问
      return true
    }
  })
  return false
}

/**
 * 设置跳转页面
 */
function setRedirectPath(){

  // 只有不包含登录页的才需要设置跳转
  const isIgnoreRoute = NoNeedLoginPath(location.href)
  if (!isIgnoreRoute){

    // 如果已经保存了，则不再保存，仅保存登录前第一次请求的页面
    // 正常情况在跳转登录页后，再未登录时也不会请求别的页面
    const loginRedirect = localStorage.getItem("loginRedirect")
    if (loginRedirect === null) {

      // 未保存历史页面，则可以保存页面
      localStorage.setItem("loginRedirect", location.href)
    }
  }

}

// 遍历菜单，解决菜单icon问题
// 手动map
const IconMap = {
  DashboardOutlined: <DashboardOutlined/>,
  SettingOutlined: <SettingOutlined/>,
  MinusCircleOutlined: <MinusCircleOutlined/>,
  PlusCircleOutlined: <PlusCircleOutlined/>
}

// 遍历方法
const loopMenuItem = (menus: MenuDataItem[]): MenuDataItem[] => {
  if (menus !== undefined && menus !== null){
    return menus.map(({ icon, routes, ...item }) => {
      return {
        //@ts-ignore
        icon: icon && IconMap[icon as string],
        routes: routes && loopMenuItem(routes),
        ...item,
      }
    });
  }return []
}

/**
 *  获取基础数据
 */
export async function getInitialState(): Promise<{
  settings?: Partial<LayoutSettings>;
  currentUser?: API.CurrentUser;
  loading?: boolean;
  menuData?: MenuDataItem[] | undefined;
  fetchUserInfo?: () => Promise<API.CurrentUser | undefined>;
  fetchUserMenus?: () => Promise<MenuDataItem[] | undefined>;
}> {
  const fetchUserInfo = async () => {
    try {
      const msg = await queryCurrentUser({
        skipErrorHandler: true,
      });
      return msg.data
    } catch (error) {

      // 如果不是社交登录界面，则跳转到登录页
      // 如果是需要增加第三方社交登录页面，则需在此添加拦截例外，否则会自动调到账号密码登录页面
      if (NoNeedLoginPath(history.location.pathname)) {
        console.log("自动登录中2...", history.location.pathname)
      }else {
        // 保存历史页面
        setRedirectPath()
        // 判断是从移动端过来的请求还是PC端的请求
        if (history.location.pathname.indexOf('/m/') !== -1) {

          // 移动端来的
          // 跳转移动端登录页面
          history.push(mobileLoginPath);
        }else {

          // 跳转PC端登录页面
          history.push(loginPath);
        }
      }
    }
    return undefined;
  };
  const fetchUserMenus = async () => {
    try {
      const res = await queryCurrentUserMenus({skipErrorHandler: true,})
      return res.data
    } catch (error) {

      // 如果不是社交登录界面，则跳转到登录页
      // 如果是需要增加第三方社交登录页面，则需在此添加拦截例外，否则会自动调到账号密码登录页面
      if (NoNeedLoginPath(history.location.pathname)) {
        console.log("自动登录中2...", history.location.pathname)
      }else {
        // 保存历史页面
        setRedirectPath()
        // 判断是从移动端过来的请求还是PC端的请求
        if (history.location.pathname.indexOf('/m/') !== -1) {

          // 移动端来的
          // 跳转移动端登录页面
          history.push(mobileLoginPath);
        }else {

          // 跳转PC端登录页面
          history.push(loginPath);
        }
      }
    }
    return undefined;
  };

  // 如果不是登录页面，执行
  if (history.location.pathname !== loginPath ) {

    const token =  localStorage.getItem('token')
    if (!token) {

      // 保存请求的路径
      // 一般是未登录，保存请求页面
      // 保存历史页面
      setRedirectPath()

      // 判断是从移动端过来的请求还是PC端的请求
      if (history.location.pathname.indexOf('/m/') !== -1) {

        // 移动端来的
        // 跳转移动端登录页面
        history.push(mobileLoginPath);
      }else {

        // 跳转PC端登录页面
        history.push(loginPath);
      }
    }else {
      const currentUser = await fetchUserInfo();
      const menuData = await fetchUserMenus();
      return {
        fetchUserInfo,
        fetchUserMenus,
        menuData,
        currentUser,
        settings: defaultSettings as Partial<LayoutSettings>,
      };
    }
  }
  return {
    fetchUserInfo,
    fetchUserMenus,
    menuData: [],
    settings: defaultSettings as Partial<LayoutSettings>,
  };
}

// ProLayout 支持的api https://procomponents.ant.design/components/layout
export const layout: RunTimeLayoutConfig = ({ initialState }) => {
  // @ts-ignore
  return {
    // actionsRender: () => [<Question key="doc" />, <SelectLang key="SelectLang" />],
    avatarProps: {
      src: initialState?.currentUser?.avatar,
      title: <AvatarName />,
      render: (_, avatarChildren) => {
        return <AvatarDropdown>{avatarChildren}</AvatarDropdown>;
      },
    },

    // 水印设置
    // waterMarkProps: {
    //   content: initialState?.currentUser?.name,
    // },

    // 顶部菜单渲染
    menuHeaderRender: undefined,

    // 自定义 403 页面
    // unAccessible: <div>unAccessible</div>,
    // 增加一个 loading 的状态
    menu: {
      locale: false,
    },
    menuDataRender: () =>{
      // @ts-ignore
      return loopMenuItem(initialState?.menuData)

    },
    ...initialState?.settings,
  };
};

//拦截器-响应后拦截
const responseInterceptors = async (response: any) => {

  // 这里是关键，获取所有接口请求成功之后的数据
  // 这里是关键，获取所有接口请求成功之后的数据，6.0返回的不用转json
  // const res = await response.clone().json();
  const res = await response;

  // 对服务器返回进行验证，如果token过期，服务器返回：code: token_not_valid
  try {

    // Token过期，如果不是登录页且不是免登陆页面的话，就跳转登录页
    if (res.data.code === 30002){
      if (NoNeedLoginPath(history.location.pathname)) {
        console.log("无需跳转登录页...", history.location.pathname)
      }else {
        message.error("登录凭证不存在或已过期，请重新登录！")

        // 保存历史页面
        setRedirectPath()
        // 判断是从移动端过来的请求还是PC端的请求
        if (history.location.pathname.indexOf('/m/') !== -1) {

          // 移动端来的
          // 跳转移动端登录页面
          history.push(mobileLoginPath);
        }else {

          // 跳转PC端登录页面
          history.push(loginPath);
        }
      }

    }else if (res.data.code === 30003){

      // 登录请求头不正确（用于带ID参数访问具体资源时，无法跳转登录页的问题）
      if (location.pathname !== loginPath) {
        if (NoNeedLoginPath(history.location.pathname)) {
          console.log("无需跳转登录页...")
        } else {
          message.error("请登录后访问！")
          localStorage.setItem("historyPath", location.toString())

          // 不是登录页，记录请求页
          setRedirectPath()
          history.push(loginPath);
        }
      }
    }else{

      // 登录成功，检查是否是首次登录

      const is_first_login = localStorage.getItem("is_first_login")
      if (is_first_login === "yes"){

        // 跳转密码修改页面
        if (history.location.pathname.indexOf("/user/firstLogin") === -1){

          // 如果不是密码修改页面，给出提示后跳转密码修改页面
          message.warning("首次登录，请先修改您的密码！")
          history.push('/user/firstLogin')
        }
      }
    }
    // 返回请求数据
    return response
  }finally {
    // 返回请求数据
    // eslint-disable-next-line no-unsafe-finally
    return response
  }
};

// 请求拦截，在请求转向后端服务器前，添加heade token认证
const authHeaderInterceptor = (url: string, options: any) => {
  let token = localStorage.getItem('token');
  if (null === token) {
    token = '';
  }
  // 如果是密码恢复页面，添加 X-CSRFToken属性，避免跨站
  if (url === "/api/user/recoverPassword" || url === "/api/user/verityCode") {
    const csrftoken = Cookie.get("csrftoken");
    const authHeader= {
      "X-CSRFToken": csrftoken
    }
    return  {
      url: url,
      options: { ...options, interceptors: true, headers: authHeader },
    };
  }

  // 如果是登录页，则不拦截，不增加Token认证头
  if (url !== '/api/user/login'){
    const authHeader = { Authorization: `Bearer ${token}` };
    return {
      url: url,
      options: { ...options, interceptors: true, headers: authHeader },
    };
  }
  return {
    url: url,
    options: { ...options, interceptors: true },
  };
};

// 拦截器配置
export const request = {
  // errorHandler,
  // 新增自动添加AccessToken的请求前拦截器
  requestInterceptors: [authHeaderInterceptor],
  responseInterceptors: [responseInterceptors]
}
